package com.its.us.web.config;

import com.its.us.web.config.filter.leave.JwtAuthenticationTokenFilter;
import com.its.us.web.config.filter.web.TokenLoginFilter;
import com.its.us.web.config.filter.web.TokenVerifyFilter;
import com.its.us.web.config.handler.JwtAuthenticationEntryPoint;
import com.its.us.web.config.handler.MyAccessDeniedHandler;
import com.its.us.web.config.hasPermission.MyPermissionEvaluator;
import com.its.us.web.service.sys.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

/**
 * @Author: master
 * @Date: 2020/10/28 20:22
 * @Version: 1.0
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Resource
    private MyAccessDeniedHandler myAccessDeniedHandler;

    @Resource
    private UserDetailsServiceImpl userDetailsServiceImpl;

    @Resource
    private MyPermissionEvaluator myPermissionEvaluator;


    @Autowired
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder
                .userDetailsService(this.userDetailsServiceImpl)
                .passwordEncoder(passwordEncoder());
    }

    /**
     * authentication：password
     *
     * @return
     * @throws Exception
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
        return new JwtAuthenticationTokenFilter();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                // 放行
                .antMatchers(
                        // todo:过滤
                        "/*",
                        //"/domain",
                        "/oauth/**",
                        "/user/login",
                        "/*.html",
                        "/favicon.ico",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js",
                        "/**/images/*.png",
                        "js/**/*.js",
                        "*.js",
                        "/**/css/*.css",
                        "/login/sban/banner.html",
                        "/login/sban/data1/images/*.jpg",
                        "/login/sban/engine1/*.png",
                        "/favicon.ico",
                        "/jquery-easyui-1.4.3/**/**/**/*.*",
                        "/domain/main.html",
                        "/**/init"
                ).permitAll()
                //配置swagger界面的匿名访问
                //.antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/swagger-ui/index.html").permitAll()
                .antMatchers("/swagger-ui/*.png").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/images/**").permitAll()
                .antMatchers("/webjars/**").permitAll()
                //.antMatchers("/v2/api-docs").permitAll()
                .antMatchers("/v3/api-docs").permitAll()
                .antMatchers("/configuration/ui").permitAll()
                .antMatchers("/configuration/security").permitAll()
                .anyRequest().authenticated();
        //.and().formLogin().permitAll()
        //.and().addFilter(new TokenLoginFilter(authenticationManagerBean()))
        //.and().addFilter(new TokenVerifyFilter(authenticationManagerBean()));

        http.exceptionHandling().accessDeniedHandler(myAccessDeniedHandler);
        http.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint);
        http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);

        http.authorizeRequests().expressionHandler(defaultWebSecurityExpressionHandler());
        // 浏览器会报“in a frame because it set 'X-Frame-Options' to 'deny'.”的错误。解决办法如下
        http.headers().frameOptions().sameOrigin().httpStrictTransportSecurity().disable();

        // disable page caching
        http.headers().cacheControl();
    }

    /**
     * password encoder
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * use has permission must impl
     *
     * @return
     */
    @Bean
    public DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler() {
        DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
        defaultWebSecurityExpressionHandler.setPermissionEvaluator(myPermissionEvaluator);
        return defaultWebSecurityExpressionHandler;
    }

}
